package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.service.base.RefundService;
import cc.rengu.igas.bsps.facade.request.TransRefundRequest;
import cc.rengu.igas.bsps.facade.response.TransRefundResponse;
import cc.rengu.igas.channel.upac.facade.response.TokenConsumeRefundResponse;
import cc.rengu.igas.channel.upac.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.RefundLimitAmtBean;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 统一支付订单退款
 */
public class UnifiedPayOrderRefundService extends RefundService implements TransCustomImpl {

    @Override
    protected Object bizBeforeCust() throws Exception {
        TransRefundRequest TransRefundRequest = new TransRefundRequest();
        ConvertUtil.convertOutput(TransRefundRequest);
        return TransRefundRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        TransRefundRequest TransRefundRequest = (TransRefundRequest) request;
        String instId = TransRefundRequest.getHeader().getInstId();
        String mchntNo = TransRefundRequest.getMchntNo();
        String orderAmt = TransRefundRequest.getOrderAmt();

        /* 原支付订单信息 */
        OrderInfo origOrderInfo = (OrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_ORDER_INFO);
        if (null == origOrderInfo) {
            rglog.error("退款交易的原支付订单不存在!");
            throw new BizException(RespCodeEnum.GET_MCHNT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_ORDER_INFO_ERROR.getRespDesc());
        }
        UserOrderInfo origUserOrderInfo = origOrderInfo.getUserOrderInfo();
        List<MchntOrderInfo> origMchntOrderInfoList = origOrderInfo.getMchntOrderInfoList();
        List<PayOrderInfo> origPayOrderInfoList = origOrderInfo.getPayOrderInfoList();

        /* 校验订单是否正在退款，防止并发退款情况 */
        String refundRedisKey = instId + mchntNo + origMchntOrderInfoList.get(0).getMchntOrderId() + orderAmt;
        rglog.debug("退款控制并发的redisKey值：<{}>", refundRedisKey);
        String exitRedisKey = RedisUtil.getAndSet(refundRedisKey, AppParamConstant.YES);
        /* 设置当前redisKey的有效时间,时间到期后redis自动删除当前key */
        RedisUtil.onceExpire(refundRedisKey, 3);
        rglog.debug("当前设置RedisKey后返回的值:<{}>", exitRedisKey);
        if (!StringUtil.isEmptyOrNull(exitRedisKey) && AppParamConstant.YES.equals(exitRedisKey)) {
            rglog.error("当前存在一笔相同退款金额的退款订单正在进行,该笔认定为重复发起的退款-不支持,refundAmt:<{}>", orderAmt);
            throw new BizException(OltpRpcdEnum.TRANS_NOT_SUPPORT.getRespCode(), OltpRpcdEnum.TRANS_NOT_SUPPORT.getRespDesc());
        }

        /* 过滤实时入账的支付订单 */
        Predicate<PayOrderInfo> d0Filter1 = p -> !ShareParamConstant.SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
        Predicate<PayOrderInfo> d0Filter2 = p -> !ShareParamConstant.OTHER_SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
        origPayOrderInfoList = origPayOrderInfoList.stream().filter(d0Filter1.and(d0Filter2))
                .sorted(Comparator.comparing(PayOrderInfo::getDstCallIndex)).collect(Collectors.toList());
        /* 获取主体支付方 */
        Predicate<PayOrderInfo> acctFilter = p -> !ChannelEnum.ACCT.getChannelType().equals(p.getMsgDstId());
        Predicate<PayOrderInfo> mompFilter = p -> !ChannelEnum.MOMP.getChannelType().equals(p.getMsgDstId());
        List<PayOrderInfo> origPayOrderInfoListFilter = origPayOrderInfoList.stream().filter(acctFilter.and(mompFilter)).collect(Collectors.toList());
        /* 判断是否为混合支付场景,若为混合支付时，也只会是主支付方式状态不明，故过滤掉非主支付方式的记录  */
        Predicate<PayOrderInfo> scoreFilter = p -> PayTypeEnum.SCORE.getPayType().equals(p.getPayType());
        if (origPayOrderInfoListFilter.stream().filter(scoreFilter).anyMatch(scoreFilter)) {
            Predicate<PayOrderInfo> mixScoreFilter = p -> !PayTypeEnum.SCORE.getPayType().equals(p.getPayType());
            origPayOrderInfoListFilter = origPayOrderInfoListFilter.stream().filter(mixScoreFilter).collect(Collectors.toList());
            GlobalTransUtil.setCacheValue(TransCacheConstant.MIX_PAY_FLAG, AppParamConstant.YES);
        }
        /* 判断是否存在商户D0实时入账的流水 */
        origPayOrderInfoListFilter = origPayOrderInfoListFilter.stream().filter(item -> !"D0".equals(item.getDstChannelType())).collect(Collectors.toList());
        if (origPayOrderInfoListFilter.size() > 1) {
            rglog.error("当前交易存在多种主支付方式，请排查是否存在主支付方式过滤问题!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        PayOrderInfo origPayOrderInfo = origPayOrderInfoListFilter.get(0);
        GlobalTransUtil.setCacheValue(TransCacheConstant.ORIG_PAY_ORDER_INFO, origPayOrderInfo);

        /*校验银联二维码主被扫的退款交易必须在一个月以内的才能退款（30天）*/
        if (PayTypeEnum.CUPS_CLOUD.getPayType().equals(origPayOrderInfo.getPayType()) && ChannelEnum.UPQC.getChannelType().equals(origPayOrderInfo.getMsgDstId())) {
            String currentDate = DateUtil.getCurrentDate();
            rglog.debug("银联二维码主被扫的交易需要校验退款的原交易必须是在30天以内的交易,oriPayOrderTxnDate:<{}>,currentDate:<{}>", origPayOrderInfo.getTxnDate(), currentDate);
            String baseDateOffsetDay = DateUtil.getBaseDateOffsetDay(origPayOrderInfo.getTxnDate(), 30);
            if (DateUtil.compareDate(currentDate, baseDateOffsetDay) > 0) {
                rglog.error("当前日期:<{}>大于原交易日期偏移30日后的日期:<{}>,即退款交易距支付交易发生日超过30天，不允许做银联二维码主被扫的退款", currentDate, baseDateOffsetDay);
                throw new BizException(OltpRpcdEnum.TRANS_NOT_SUPPORT.getRespCode(), OltpRpcdEnum.TRANS_NOT_SUPPORT.getRespDesc());
            }
        }

        /* 退款订单校验以及生成退款订单信息 */
        OrderInfo refundOrderInfo;
        String bizSceneType = origOrderInfo.getMchntOrderInfoList().get(0).getBizSceneType();
        if ("00".equals(bizSceneType) || "02".equals(bizSceneType)) {
            if ("00".equals(bizSceneType)) {
                //营销平台购买卡卷标识
                GlobalTransUtil.setCacheValue(TransCacheConstant.MOMP_BUY_COUPON_FLAG, AppParamConstant.YES);
            }
            //购买卡卷场景退款
            refundOrderInfo = couponRefundCheck(TransRefundRequest, origUserOrderInfo, origMchntOrderInfoList, origPayOrderInfo);
        } else if ("01".equals(bizSceneType)) {
            //担保支付场景退款
            refundOrderInfo = guaranteeRefundCheck(TransRefundRequest, origUserOrderInfo, origMchntOrderInfoList, origPayOrderInfo);
        } else {
            //其它场景退款
            refundOrderInfo = normalRefundCheck(TransRefundRequest, origUserOrderInfo, origMchntOrderInfoList, origPayOrderInfo);
        }
        //登记退款订单信息
        OrderService orderService = new OrderServiceImpl();
        refundOrderInfo.getUserOrderInfo().setUserOrderId(orderService.generateUserOrderId());
        if (!orderService.registerOrderInfo(refundOrderInfo.getUserOrderInfo(), refundOrderInfo.getMchntOrderInfoList(), null)) {
            rglog.error("登记退款订单信息失败!");
            throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
        }
        //将退款商户订单放到交易缓存中，用于退款成功时更新商户累计限额
        GlobalTransUtil.setCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST, refundOrderInfo.getMchntOrderInfoList());

        //调用通道接口
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(TransRefundRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, refundOrderInfo, channelCallCfg.getBizScene(), request);

        //异步注册退款查证服务
        int iReturnCode = asynnotify.transactionNotice(ShareServiceConstant.ASYN_PAYORDERSTATUS_QUERY_SERVICE, 5, AsynNotify.GAP_SAME, 60 * 1000);
        if (iReturnCode != 0) {
            rglog.error("异步调起全渠道交易状态查询失败,iReturnCode:{}", iReturnCode);
        }

        //组装应答结果
        TransRefundResponse TransRefundResponse = new TransRefundResponse();
        TransRefundResponse.setSysSeqNum(refundOrderInfo.getUserOrderInfo().getSysSeqNum());
        BizResponse bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(TransRefundResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        TransRefundResponse TransRefundResponse = (TransRefundResponse) bizResponse.getResult();
        ConvertUtil.convertInput(TransRefundResponse);
    }

    /**
     * 购买卡卷交易退款
     *
     * @param TransRefundRequest      退款请求信息
     * @param origUserOrderInfo       原支付用户订单信息
     * @param origMchntOrderInfoiList 原支付商户订单信息
     * @param origPayOrderInfo        原支付支付订单信息
     * @return 退款订单信息
     * @throws Exception 异常
     */
    private OrderInfo couponRefundCheck(TransRefundRequest TransRefundRequest, UserOrderInfo origUserOrderInfo, List<MchntOrderInfo> origMchntOrderInfoiList, PayOrderInfo origPayOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderInfo refundOrderInfo = new OrderInfo();
        String instId = TransRefundRequest.getHeader().getInstId();
        String txnNum = TransRefundRequest.getHeader().getTxnNum();
        String bizType = TransRefundRequest.getHeader().getBizType();
        String refundAmt = TransRefundRequest.getOrderAmt();
        String realPayAmt = origPayOrderInfo.getRealPayAmt();
        String orderAllRefundFlag = xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.ORDER_ALL_REFUND_FLAG);

        //检查商户状态
        MchntService mchntService = new MchntServiceImpl();
        boolean checkResult = mchntService.checkMchntStatus(instId, origMchntOrderInfoiList.get(0).getMchntNo());
        if (!checkResult) {
            rglog.error("商户<{}>不存在或者商户状态异常!", origMchntOrderInfoiList.get(0).getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
        }
        //交易权限检查
        checkResult = mchntService.checkMchntAuth(instId, origMchntOrderInfoiList.get(0).getMchntNo(), null, txnNum, bizType, AcctTypeEnum.ALL.getAcctType());
        if (!checkResult) {
            rglog.error("商户<{}>无此交易权限!", origMchntOrderInfoiList.get(0).getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
        }
        //交易限额检查
        LimitAcctTypeEnum limitAcctTypeEnum = LimitAcctTypeEnum.getAcctType(origPayOrderInfo.getPayerAcctType());
        int limitFlag = mchntService.checkMchntTransLimit(instId, origMchntOrderInfoiList.get(0).getOrderAmt(), limitAcctTypeEnum, origMchntOrderInfoiList.get(0).getMchntNo(), null, txnNum);
        if (limitFlag == 2 || limitFlag == 3) {
            rglog.error("商户金额超限");
            throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
        }
        //生成退款交易商户订单信息
        MchntOrderInfo mchntRefundOrderInfo = generateRefundMchntOrderInfo(origMchntOrderInfoiList.get(0), TransRefundRequest.getOrderAmt(), origMchntOrderInfoiList.get(0).getOrderDiscountAmt());
        refundOrderInfo.setMchntOrderInfoList(Collections.singletonList(mchntRefundOrderInfo));
        //生成退款用户订单
        if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
            //全额退款时用户退款金额使用原支付订单的实际支付金额,全额退款时退款金额使用原商户订单表中的订单金额
            rglog.debug("担保支付出现全额退款时用户退款金额使用原支付订单的实际支付金额:<{}>", origPayOrderInfo.getRealPayAmt());
            realPayAmt = origPayOrderInfo.getRealPayAmt();
        }
        UserOrderInfo refundUserOrderInfo = generateRefundUserOrderInfo(origUserOrderInfo, refundAmt, realPayAmt);
        refundOrderInfo.setUserOrderInfo(refundUserOrderInfo);
        return refundOrderInfo;
    }

    /**
     * 担保支付交易退款
     *
     * @param TransRefundRequest      退款请求信息
     * @param origUserOrderInfo       原支付用户订单信息
     * @param origMchntOrderInfoiList 原支付商户订单信息
     * @param origPayOrderInfo        原支付支付订单信息
     * @return 退款订单信息
     * @throws Exception 异常
     */
    private OrderInfo guaranteeRefundCheck(TransRefundRequest TransRefundRequest, UserOrderInfo origUserOrderInfo, List<MchntOrderInfo> origMchntOrderInfoiList, PayOrderInfo origPayOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderInfo refundOrderInfo = new OrderInfo();
        String instId = TransRefundRequest.getHeader().getInstId();
        String txnNum = TransRefundRequest.getHeader().getTxnNum();
        String orderAllRefundFlag = xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.ORDER_ALL_REFUND_FLAG);
        String refundAmt = TransRefundRequest.getOrderAmt();
        String realPayAmt = origPayOrderInfo.getRealPayAmt();

        //担保支付出现全额退款时用户退款金额使用原支付订单的实际支付金额,全额退款时退款金额使用原商户订单表中的订单金额
        if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
            rglog.debug("担保支付出现全额退款时用户退款金额使用原支付订单的实际支付金额:<{}>", origPayOrderInfo.getRealPayAmt());
            realPayAmt = origPayOrderInfo.getRealPayAmt();
        }

        MchntService mchntService = new MchntServiceImpl();
        for (MchntOrderInfo origMchntOrderInfo : origMchntOrderInfoiList) {
            //获取当前商户退款的金额,全订单退款时使用原商户订单的订单金额，非全订单退款使用上送的退款订单金额
            String mchntRefundAmt = refundAmt;
            if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
                mchntRefundAmt = origMchntOrderInfo.getOrderAmt();
            }
            //检查商户状态
            boolean checkResult = mchntService.checkMchntStatus(instId, origMchntOrderInfo.getMchntNo());
            if (!checkResult) {
                rglog.error("商户<{}>不存在或者商户状态异常!", origMchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
            }
            //当日支付交易与退款交易的限额检查
            if (BizStatusEnum.FINISH.getStatus().equals(origMchntOrderInfo.getBizStatus()) || BizStatusEnum.NOT_CONFIRM_PART_REFUND.getStatus().equals(origMchntOrderInfo.getBizStatus())) {
                rglog.info("担保支付未确认收货不检查当天累计限额");
            } else {
                checkResult = mchntService.checkMchntRefundLimit(instId, origMchntOrderInfo.getMchntNo(), mchntRefundAmt);
                if (!checkResult) {
                    rglog.error("当天累计支付金额小于累计退款金额");
                    throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
                }
            }
            //交易限额检查
            LimitAcctTypeEnum limitAcctTypeEnum = LimitAcctTypeEnum.getAcctType(Objects.requireNonNull(origPayOrderInfo).getPayerAcctType());
            int limitFlag = mchntService.checkMchntTransLimit(instId, mchntRefundAmt, limitAcctTypeEnum, origMchntOrderInfo.getMchntNo(), null, txnNum);
            if (limitFlag == 2 || limitFlag == 3) {
                rglog.error("商户金额超限");
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            }
            //判断商户是否享受手续费营销
            if (!StringUtil.isEmptyOrNull(origMchntOrderInfo.getMchntDiscountFee()) && AmountUtil.compare(origMchntOrderInfo.getMchntDiscountFee(), "0.00") > 0) {
                rglog.info("商户:<{}>享受手续费营销，手续费优惠金额:<{}>", origMchntOrderInfo.getMchntNo(), origMchntOrderInfo.getMchntDiscountFee());
                xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.MCHNT_FEE_JOIN_MOMP, AppParamConstant.YES);
            }
            //判断原支付是否参与了营销
            if (origMchntOrderInfo.getCustomerMarketAmt() != null && AmountUtil.compare(origMchntOrderInfo.getCustomerMarketAmt(), "0.00") != 0) {
                realPayAmt = AmountUtil.subtraction(realPayAmt, origMchntOrderInfo.getCustomerMarketAmt());
            }
            //生成退款交易商户订单信息
            MchntOrderInfo refundMchntOrderInfo = generateRefundMchntOrderInfo(origMchntOrderInfo, TransRefundRequest.getOrderAmt(), origMchntOrderInfo.getOrderDiscountAmt());
            refundOrderInfo.setMchntOrderInfoList(Collections.singletonList(refundMchntOrderInfo));
        }

        //生成退款用户订单
        if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
            //全额退款时用户退款金额使用原支付订单的实际支付金额,全额退款时退款金额使用原商户订单表中的订单金额
            rglog.debug("全额退款时用户退款金额使用原支付订单的实际支付金额:<{}>", origPayOrderInfo.getRealPayAmt());
            realPayAmt = origPayOrderInfo.getRealPayAmt();
        }
        UserOrderInfo refundUserOrderInfo = generateRefundUserOrderInfo(origUserOrderInfo, refundAmt, realPayAmt);
        refundOrderInfo.setUserOrderInfo(refundUserOrderInfo);
        return refundOrderInfo;
    }

    /**
     * 普通支付交易退款
     *
     * @param TransRefundRequest      退款请求信息
     * @param origUserOrderInfo       原支付用户订单信息
     * @param origMchntOrderInfoiList 原支付商户订单信息
     * @param origPayOrderInfo        原支付支付订单信息
     * @return 退款订单信息
     * @throws Exception 异常
     */
    private OrderInfo normalRefundCheck(TransRefundRequest TransRefundRequest, UserOrderInfo origUserOrderInfo, List<MchntOrderInfo> origMchntOrderInfoiList, PayOrderInfo origPayOrderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderInfo refundOrderInfo = new OrderInfo();
        String instId = TransRefundRequest.getHeader().getInstId();
        String txnNum = TransRefundRequest.getHeader().getTxnNum();
        String bizType = TransRefundRequest.getHeader().getBizType();
        String refundAmt = TransRefundRequest.getOrderAmt();
        String realPayAmt = origPayOrderInfo.getRealPayAmt();
        String orderAllRefundFlag = xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.ORDER_ALL_REFUND_FLAG);

        MchntService mchntService = new MchntServiceImpl();
        if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.DISCOUNT_FLAG, AppParamConstant.YES);
        } else {
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.DISCOUNT_FLAG, AppParamConstant.NO);
            if (StringUtil.isEmptyOrNull(TransRefundRequest.getMchntNo())) {
                rglog.error("单商户退款，退款商户号<{}>必须上送!", TransRefundRequest.getMchntNo());
            }
            //原商户订单号只过滤退款商户的记录
            origMchntOrderInfoiList = origMchntOrderInfoiList.stream().filter(item -> item.getMchntNo().equals(TransRefundRequest.getMchntNo())).collect(Collectors.toList());
        }

        List<RefundLimitAmtBean> refundLimitAmtBeanList = new ArrayList<>();
        for (MchntOrderInfo origMchntOrderInfo : origMchntOrderInfoiList) {
            //判断商户是否享受手续费营销
            if (!StringUtil.isEmptyOrNull(origMchntOrderInfo.getMchntDiscountFee()) && AmountUtil.compare(origMchntOrderInfo.getMchntDiscountFee(), "0.00") > 0) {
                rglog.info("商户:<{}>享受手续费营销，手续费优惠金额:<{}>", origMchntOrderInfo.getMchntNo(), origMchntOrderInfo.getMchntDiscountFee());
                xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.MCHNT_FEE_JOIN_MOMP, AppParamConstant.YES);
            }
            //检查商户状态
            MchntInfo mchntInfo = mchntService.getMchntInfo(instId, origMchntOrderInfo.getMchntNo());
            if (null == mchntInfo) {
                rglog.error("商户<{}>不存在或者商户状态异常!", origMchntOrderInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
            }
            //非独立清算门店，累计到连锁门店计算退款限额
            rglog.debug("检查商户退款限额,独立清算的门店商户需要校验当天累计退款金额是否小于当天已发生的正交易金额,mchntType-11:<{}>,independentDataFlag:<{}>", mchntInfo.getMchntType(), mchntInfo.getIndependentDataFlag());
            if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                RefundLimitAmtBean refundLimitAmtBean = new RefundLimitAmtBean();
                refundLimitAmtBean.setMchntNo(mchntInfo.getChainMchntNo());
                refundLimitAmtBean.setRefundAmt(origMchntOrderInfo.getOrderAmt());
                refundLimitAmtBeanList.add(refundLimitAmtBean);
            } else {
                //检查商户当天支付总额 >= (商户当天退款总额(包含退款中)+本次退款金额）方能退款,担保订单未确认收货不检查
                boolean checkResult = mchntService.checkMchntRefundLimit(instId, origMchntOrderInfo.getMchntNo(), origMchntOrderInfo.getOrderAmt());
                if (!checkResult) {
                    rglog.error("当天累计支付金额小于累计退款金额");
                    throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
                }
            }
            /*交易权限检查*/
            boolean checkResult = mchntService.checkMchntAuth(instId, origMchntOrderInfoiList.get(0).getMchntNo(), null, txnNum, bizType, AcctTypeEnum.ALL.getAcctType());
            if (!checkResult) {
                rglog.error("商户<{}>无此交易权限!", origMchntOrderInfoiList.get(0).getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
            }
            //交易限额检查
            LimitAcctTypeEnum limitAcctTypeEnum = LimitAcctTypeEnum.getAcctType(Objects.requireNonNull(origPayOrderInfo).getPayerAcctType());
            int limitFlag = mchntService.checkMchntTransLimit(instId, origMchntOrderInfo.getOrderAmt(), limitAcctTypeEnum, origMchntOrderInfo.getMchntNo(), null, txnNum);
            if (limitFlag == 2 || limitFlag == 3) {
                rglog.error("商户金额超限");
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            }
            //判断原支付是否参与了营销
            if (origMchntOrderInfo.getCustomerMarketAmt() != null && AmountUtil.compare(origMchntOrderInfo.getCustomerMarketAmt(), "0.00") != 0) {
                realPayAmt = AmountUtil.subtraction(realPayAmt, origMchntOrderInfo.getCustomerMarketAmt());
            }
            //生成退款交易商户订单信息
            MchntOrderInfo refundMchntOrderInfo = generateRefundMchntOrderInfo(origMchntOrderInfo, TransRefundRequest.getOrderAmt(), origMchntOrderInfo.getOrderDiscountAmt());
            refundOrderInfo.setMchntOrderInfoList(Collections.singletonList(refundMchntOrderInfo));
        }
        //检查非独立清算连锁商户退款限额
        if (!refundLimitAmtBeanList.isEmpty()) {
            //设置是否是连锁商户下非独立清算的门店退款标示，在检查当日支付金额不小于退款金额时使用
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.CHAIN_MCHNT_ORDER_FLAG, AppParamConstant.YES);
            //按商户分组去重，累计求和
            String totalRefundAmt = "0.00";
            Map<String, List<RefundLimitAmtBean>> groupByMchntNo = refundLimitAmtBeanList.stream().collect(Collectors.groupingBy(RefundLimitAmtBean::getMchntNo));
            for (Map.Entry<String, List<RefundLimitAmtBean>> entryMchntNo : groupByMchntNo.entrySet()) {
                String chainMchntNo = entryMchntNo.getKey();
                List<RefundLimitAmtBean> entryMchtAdjustDetailList = entryMchntNo.getValue();
                for (RefundLimitAmtBean refundLimitAmtBean : entryMchtAdjustDetailList) {
                    totalRefundAmt = AmountUtil.addition(totalRefundAmt, refundLimitAmtBean.getRefundAmt());
                }
                boolean checkResult = mchntService.checkMchntRefundLimit(instId, chainMchntNo, totalRefundAmt);
                if (!checkResult) {
                    rglog.error("当天累计支付金额小于累计退款金额");
                    throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
                }
            }
        }

        //生成退款用户订单
        if (AppParamConstant.YES.equals(orderAllRefundFlag)) {
            //全额退款时用户退款金额使用原支付订单的实际支付金额,全额退款时退款金额使用原商户订单表中的订单金额
            rglog.debug("全额退款时用户退款金额使用原支付订单的实际支付金额:<{}>", origPayOrderInfo.getRealPayAmt());
            realPayAmt = origPayOrderInfo.getRealPayAmt();
        }
        UserOrderInfo refundUserOrderInfo = generateRefundUserOrderInfo(origUserOrderInfo, refundAmt, realPayAmt);
        refundOrderInfo.setUserOrderInfo(refundUserOrderInfo);
        return refundOrderInfo;
    }

    /**
     * 生成退款用户订单信息
     *
     * @param origUserOrderInfo 原支付用户订单信息
     * @param refundAmt         退款金额
     * @param realPayAmt        实际退款给用户的支付金额
     * @return 退款用户订单信息
     * @throws Exception 异常
     */
    private UserOrderInfo generateRefundUserOrderInfo(UserOrderInfo origUserOrderInfo, String refundAmt, String realPayAmt) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UserOrderInfo refundUserOrderInfo = new UserOrderInfo();
        ConvertUtil.convertOutput(refundUserOrderInfo);
        if (xmlTreeUtil.isExist(ShareTreeNodeConstant.MCHNT_REFUND_ID)) {
            refundUserOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.MCHNT_REFUND_ID));
        } else {
            refundUserOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        }
        refundUserOrderInfo.setOrderAmt(refundAmt);
        refundUserOrderInfo.setNeedPayAmt(refundAmt);
        refundUserOrderInfo.setRealPayAmt(realPayAmt);
        refundUserOrderInfo.setRealDiscountAmt(origUserOrderInfo.getRealDiscountAmt());
        refundUserOrderInfo.setOrderCcy(origUserOrderInfo.getOrderCcy());
        refundUserOrderInfo.setOrigTxnDate(origUserOrderInfo.getTxnDate());
        refundUserOrderInfo.setOrigSysSeqNum(origUserOrderInfo.getSysSeqNum());
        refundUserOrderInfo.setTransChannelId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID));
        refundUserOrderInfo.setGroupMchntNo(origUserOrderInfo.getGroupMchntNo());
        refundUserOrderInfo.setGroupMchntName(origUserOrderInfo.getGroupMchntName());
        refundUserOrderInfo.setOrderCreateTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"));
        refundUserOrderInfo.setOrderExpiryTime(DateUtil.getPastOrFutureDayTime(refundUserOrderInfo.getOrderCreateTime(), "yyyyMMddHHmmss", "M", 30));
        refundUserOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        refundUserOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        refundUserOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        refundUserOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return refundUserOrderInfo;
    }

    /**
     * 生成退款商户订单信息
     *
     * @param origMchntOrderInfo 原支付商户订单信息
     * @param mchntRefundAmt     商户退款金额
     * @param orderDiscountAmt   退款订单优惠金额
     * @return 退款商户订单信息
     * @throws Exception 异常
     */
    private MchntOrderInfo generateRefundMchntOrderInfo(MchntOrderInfo origMchntOrderInfo, String mchntRefundAmt, String orderDiscountAmt) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /*获取原退款成功商户订单列表*/
        String refundedAmt = "0.00";
        String refundTotalFee = "0.00";
        String refundRealSettleAmt = "0.00";
        String comfirmedFee = "0.00";
        String comfirmedAmt = "0.00";
        String refundRealTotalFee = "0.00";
        String comfirmRealSettleAmt = "0.00";
        //获取已经退款的商户订单信息
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> refundMchntOrderInfos = mchntOrderInfoMapper.selectMchntOrderInfoByOrigSysSeqNum(origMchntOrderInfo.getInstId(), origMchntOrderInfo.getSysSeqNum());
        if (refundMchntOrderInfos != null && !refundMchntOrderInfos.isEmpty()) {
            String mchntNo = origMchntOrderInfo.getMchntNo();
            refundMchntOrderInfos = refundMchntOrderInfos.stream().filter(item -> item.getMchntNo().equals(mchntNo)).collect(Collectors.toList());
            if (!refundMchntOrderInfos.isEmpty()) {
                //担保支付退款的需要判断 已退款金额和已担保支付确认金额之和比较原商户订单金额
                for (MchntOrderInfo mchntOrderInfoSuc : refundMchntOrderInfos) {
                    //退款订单 交易状态为成功或则超时 业务状态为业务处理成功或未确认收货部分退款或业务处理中 的退款交易
                    if (TransTypeEnum.REFUND.equals(TransTypeEnum.getTransType(mchntOrderInfoSuc.getTxnNum()))) {
                        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(mchntOrderInfoSuc.getTransStatus()) || TransStatusEnum.TRANS_TIMEOUT.getStatus().equals(mchntOrderInfoSuc.getTransStatus())) {
                            if (BizStatusEnum.FINISH.getStatus().equals(mchntOrderInfoSuc.getBizStatus())
                                    || BizStatusEnum.NOT_CONFIRM_PART_REFUND.getStatus().equals(mchntOrderInfoSuc.getBizStatus())
                                    || BizStatusEnum.PART_REFUND.getStatus().equals(mchntOrderInfoSuc.getBizStatus())
                                    || BizStatusEnum.PROCESSING.getStatus().equals(mchntOrderInfoSuc.getBizStatus())) {
                                refundTotalFee = AmountUtil.addition(refundTotalFee, mchntOrderInfoSuc.getMchntFee());
                                refundRealTotalFee = AmountUtil.addition(refundRealTotalFee, mchntOrderInfoSuc.getRealMchntFee());
                                refundedAmt = AmountUtil.addition(refundedAmt, mchntOrderInfoSuc.getOrderAmt());
                                refundRealSettleAmt = AmountUtil.addition(refundRealSettleAmt, mchntOrderInfoSuc.getRealSettleAmt());
                            }
                        }
                    } else {
                        //担保支付确认订单 交易状态为成功或则超时
                        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(mchntOrderInfoSuc.getTransStatus())
                                || TransStatusEnum.TRANS_TIMEOUT.getStatus().equals(mchntOrderInfoSuc.getTransStatus())) {
                            if (BizStatusEnum.FINISH.getStatus().equals(mchntOrderInfoSuc.getBizStatus())
                                    || BizStatusEnum.PROCESSING.getStatus().equals(mchntOrderInfoSuc.getBizStatus())) {
                                comfirmedFee = AmountUtil.addition(comfirmedFee, mchntOrderInfoSuc.getRealMchntFee());
                                comfirmedAmt = AmountUtil.addition(comfirmedAmt, mchntOrderInfoSuc.getOrderAmt());
                                comfirmRealSettleAmt = AmountUtil.addition(comfirmRealSettleAmt, mchntOrderInfoSuc.getRealSettleAmt());
                            }
                        }
                    }
                }
            }
        }
        rglog.info("已退款的商户应退手续费:<{}>", refundTotalFee);
        rglog.info("已退款的商户实退手续费:<{}>", refundRealTotalFee);
        rglog.info("已退款的订单金额:<{}>", refundedAmt);
        rglog.info("已退款的商户清算本金:<{}>", refundRealSettleAmt);
        rglog.debug("已确认收货的商户实收手续费:<{}>", comfirmedFee);
        rglog.debug("已确认收货的订单金额:<{}>", comfirmedAmt);
        rglog.debug("已确认收货的商户清算本金:<{}>", comfirmRealSettleAmt);

        //判断已确认收货金额+已退款金额+本次退款订单金额 是否大于原商户订单金额
        rglog.debug("本次退款发生的金额:<{}>", mchntRefundAmt);
        String totalOrderAmt = AmountUtil.addition(refundedAmt, mchntRefundAmt);
        if (AmountUtil.compare(totalOrderAmt, origMchntOrderInfo.getOrderAmt()) == 1) {
            rglog.error("已退款金额:<{}>+本次退款金额:<{}>大于原商户订单的金额:<{}>,不允许退款", refundedAmt, mchntRefundAmt, origMchntOrderInfo.getOrderAmt());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }

        MchntOrderInfo refundMchntOrderInfo = new MchntOrderInfo();
        ConvertUtil.convertOutput(refundMchntOrderInfo);
        if (xmlTreeUtil.isExist(ShareTreeNodeConstant.MCHNT_REFUND_ID)) {
            refundMchntOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.MCHNT_REFUND_ID));
        } else {
            refundMchntOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        }
        refundMchntOrderInfo.setBizProdCode(origMchntOrderInfo.getBizProdCode());
        refundMchntOrderInfo.setBizSceneType(origMchntOrderInfo.getBizSceneType());
        refundMchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
        refundMchntOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        refundMchntOrderInfo.setTxnDate(DateUtil.getCurrentDate());
        refundMchntOrderInfo.setTxnTime(DateUtil.getCurrentTime());
        refundMchntOrderInfo.setOrderAmt(mchntRefundAmt);
        refundMchntOrderInfo.setOrderDiscountAmt(orderDiscountAmt);
        refundMchntOrderInfo.setOrderCcy(origMchntOrderInfo.getOrderCcy());
        refundMchntOrderInfo.setFeeInputMode(origMchntOrderInfo.getFeeInputMode());
        refundMchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        refundMchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        refundMchntOrderInfo.setOrigSysSeqNum(origMchntOrderInfo.getSysSeqNum());
        refundMchntOrderInfo.setOrigTxnDate(origMchntOrderInfo.getTxnDate() + origMchntOrderInfo.getTxnTime());
        refundMchntOrderInfo.setAcqInstCode(origMchntOrderInfo.getAcqInstCode());
        refundMchntOrderInfo.setIndustryType(origMchntOrderInfo.getIndustryType());
        refundMchntOrderInfo.setMchntNo(origMchntOrderInfo.getMchntNo());
        refundMchntOrderInfo.setMchntName(origMchntOrderInfo.getMchntName());
        refundMchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (AmountUtil.compare(totalOrderAmt, origMchntOrderInfo.getOrderAmt()) == 0) {
            //当前这笔退款为最后一次退款，对客营销金额赋值为原支付交易中商户订单的对客营销金额
            refundMchntOrderInfo.setCustomerMarketAmt(origMchntOrderInfo.getCustomerMarketAmt());
            refundMchntOrderInfo.setFeeRate(origMchntOrderInfo.getFeeRate());
            refundMchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(origMchntOrderInfo.getRealSettleAmt(), refundRealSettleAmt));
            refundMchntOrderInfo.setMchntFee(AmountUtil.subtraction(origMchntOrderInfo.getMchntFee(), refundTotalFee));
            refundMchntOrderInfo.setRealMchntFee(AmountUtil.subtraction(origMchntOrderInfo.getRealMchntFee(), refundTotalFee));
            refundMchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(refundMchntOrderInfo.getRealSettleAmt(), refundMchntOrderInfo.getRealMchntFee()));
            origMchntOrderInfo.setRefundAmt(totalOrderAmt);
            origMchntOrderInfo.setRefundFee(origMchntOrderInfo.getMchntFee());
            origMchntOrderInfo.setRealRefundFee(origMchntOrderInfo.getRealMchntFee());
        } else {
            //当前这笔退款为部分退款
            if (xmlTreeUtil.isExist(TreeNodeConstant.REAL_SETTLE_AMT)) {
                refundMchntOrderInfo.setRealSettleAmt(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.REAL_SETTLE_AMT));
            } else {
                refundMchntOrderInfo.setRealSettleAmt(mchntRefundAmt);
            }
            //特殊计费或者原支付交易未计算手续费时，退款交易都不计算商户手续费等信息
            if (!StringUtil.isEmptyOrNull(origMchntOrderInfo.getFeeInputMode()) && !"0".equals(origMchntOrderInfo.getFeeInputMode())) {
                //计算退款的手续费
                MchntService mchntService = new MchntServiceImpl();
                boolean calcFlag = mchntService.calcMchntRefundFee(refundMchntOrderInfo, origMchntOrderInfo);
                if (!calcFlag) {
                    rglog.error("计算商户手续费失败!");
                    throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
                }
                origMchntOrderInfo.setRefundFee(AmountUtil.addition(refundTotalFee, refundMchntOrderInfo.getRefundFee()));
            }
            /*固定金额手续费退款时，当前退款金额+商户累计退款金额<= 商户结算净额(部分退款)*/
            rglog.debug("原支付订单信息<{}>", JSON.toJSONString(origMchntOrderInfo));
            if ("2".equals(origMchntOrderInfo.getFeeInputMode()) &&
                    AmountUtil.compare(origMchntOrderInfo.getRefundAmt(), origMchntOrderInfo.getRealSettleAmt()) == -1 &&
                    AmountUtil.compare(origMchntOrderInfo.getMchntSettleAmt(), origMchntOrderInfo.getRefundAmt()) == -1) {
                rglog.error("商户为固定金额收取手续费，部分退款的累计退款金额<{}>大于商户结算净额<{}>,不允许退款", origMchntOrderInfo.getRefundAmt(), origMchntOrderInfo.getMchntSettleAmt());
                throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
            }
            /*原商户支付订单累计退款金额、手续费*/
            if (origMchntOrderInfo.getRefundAmt() == null || origMchntOrderInfo.getRefundAmt().isEmpty()) {
                origMchntOrderInfo.setRefundAmt(mchntRefundAmt);
            } else {
                origMchntOrderInfo.setRefundAmt(AmountUtil.addition(refundedAmt, mchntRefundAmt));
            }
            origMchntOrderInfo.setRefundFee(AmountUtil.addition(refundMchntOrderInfo.getRefundFee(), refundTotalFee));
        }
        return refundMchntOrderInfo;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt;
        String mompBuyCouponFlag = (String) GlobalTransUtil.getCacheValue(TransCacheConstant.MOMP_BUY_COUPON_FLAG);
        PayOrderInfo origPayOrderInfo = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_PAY_ORDER_INFO);
        if (!StringUtil.isEmptyOrNull(mompBuyCouponFlag) && AppParamConstant.YES.equals(mompBuyCouponFlag)) {
            //营销平台购买卡卷场景
            if (null != origPayOrderInfo && ChannelEnum.ESB.getChannelType().equals(origPayOrderInfo.getMsgDstId())) {
                if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(origPayOrderInfo.getPayerAcctType())) {
                    channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("03")).findFirst();
                } else {
                    channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("02")).findFirst();
                }
            } else {
                channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).findFirst();
            }
        } else {
            //非营销平台购买卡卷场景
            if (null != origPayOrderInfo && ChannelEnum.ESB.getChannelType().equals(origPayOrderInfo.getMsgDstId())) {
                if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(origPayOrderInfo.getPayerAcctType())) {
                    channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).findFirst();
                } else {
                    channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).findFirst();
                }
            } else {
                channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).findFirst();
            }
        }
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        if (ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())) {
            if ("0000".equals(channelCallCfg.getCallIndex())) {
                //锁定卡卷
                GlobalTransUtil.setCacheValue(TransCacheConstant.COUPON_LOCK_FLAG, "0");
            } else if ("0401".equals(channelCallCfg.getCallIndex())) {
                //锁定卡卷解锁(不退还给用户)
                GlobalTransUtil.setCacheValue(TransCacheConstant.COUPON_LOCK_FLAG, "2");
            } else if ("".equals(channelCallCfg.getCallIndex())) {
                //卡卷回退(卡卷返还给用户)
                GlobalTransUtil.setCacheValue(TransCacheConstant.COUPON_LOCK_FLAG, "1");
            }
        } else if (ChannelEnum.ACCT.getChannelType().equals(channelCallCfg.getCallChannelId())) {
            OrderInfo origOrderInfo = (OrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_ORDER_INFO);
            if (null != origOrderInfo && null != origOrderInfo.getMchntOrderInfoList()) {
                MchntOrderInfo origMchntOrderInfo = origOrderInfo.getMchntOrderInfoList().get(0);
                String bizSceneType = origMchntOrderInfo.getBizSceneType();
                String feeInputMode = origMchntOrderInfo.getFeeInputMode();
                String confirmFlag = (String) GlobalTransUtil.getCacheValue(TransCacheConstant.ORDER_COMFIRM_FLAG);
                if ("00".equals(bizSceneType) || "02".equals(bizSceneType) || "0".equals(feeInputMode) ||
                        StringUtil.isEmptyOrNull(origMchntOrderInfo.getMchntFee()) || ("01".equals(bizSceneType) && AppParamConstant.NO.equals(confirmFlag))) {
                    rglog.info("购买卡券、特殊费率、原交易未计算商户手续费、担保订单未确认收货的交易不记虚拟账!");
                    return CheckResultEnum.NEXT;
                }
            }
        }
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
            if (ChannelEnum.WXZF.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.UPWX.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                    ChannelEnum.NUWX.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.ALIP.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                    ChannelEnum.UPAL.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.NUAL.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                    ChannelEnum.UPAC.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.NCQS.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                    ChannelEnum.UPGW.getChannelType().equals(channelCallCfg.getCallChannelId()) || ChannelEnum.CPCN.getChannelType().equals(channelCallCfg.getCallChannelId()) ||
                    ChannelEnum.ESB.getChannelType().equals(channelCallCfg.getCallChannelId())) {
                XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
                String refundType = xmlTreeUtil.getXmlTreeStringValue(ShareTreeNodeConstant.REFUND_TYPE);
                OrderInfo origOrderInfo = (OrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_ORDER_INFO);
                List<MchntOrderDetail> origMchneOrderDetailList = (List<MchntOrderDetail>) GlobalTransUtil.getCacheValue(TransCacheConstant.MCHNT_ORDER_DETAIL_LIST);
                PayOrderInfo origPayOrderInfo = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_PAY_ORDER_INFO);
                UserOrderInfo origUserOrderInfo = Objects.requireNonNull(origOrderInfo).getUserOrderInfo();
                List<MchntOrderInfo> origMchntOrderInfoList = origOrderInfo.getMchntOrderInfoList();
                rglog.debug("获取原用户的业务状态。用户订单是否全额退款:<{}>,原商户订单业务场景类型:<{}>", refundType, origMchntOrderInfoList.get(0).getBizSceneType());
                if ("01".equals(origMchntOrderInfoList.get(0).getBizSceneType())) {
                    rglog.debug("原订单为担保支付,根据用户订单业务状态:<{}>判断是已确认退款还是未确认收货的退款", origUserOrderInfo.getBizStatus());
                    if (BizStatusEnum.CONFIRM.getStatus().equals(origUserOrderInfo.getBizStatus())
                            || BizStatusEnum.PART_REFUND.getStatus().equals(origUserOrderInfo.getBizStatus())) {
                        if (AppParamConstant.YES.equals(refundType)) {
                            origUserOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
                        } else {
                            origUserOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
                        }
                    } else {
                        if (AppParamConstant.YES.equals(refundType)) {
                            origUserOrderInfo.setBizStatus(BizStatusEnum.NOT_CONFIRM_REFUND.getStatus());
                        } else {
                            origUserOrderInfo.setBizStatus(BizStatusEnum.NOT_CONFIRM_PART_REFUND.getStatus());
                        }
                        //记录当前订单是否是未确认收货的担保支付订单，在预授权完成处理逻辑中进行退款推送消息时判断若是未确认收货的退款订单就不推送消息并且不记预授权完成
                        xmlTreeUtil.setXmlTreeStringValue("ISNOTCOMFIRMORDER", AppParamConstant.YES);
                    }
                } else {
                    if (AppParamConstant.YES.equals(refundType)) {
                        origUserOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
                    } else {
                        origUserOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
                    }
                }
                origUserOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                for (MchntOrderInfo mchntOrderInfo : origMchntOrderInfoList) {
                    rglog.debug("判断原商户订单是否全额退款，商户业务场景:<{}>,商户订单金额:<{}>,商户退款金额:<{}>,原商户订单业务状态:<{}>",
                            mchntOrderInfo.getBizSceneType(), mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getRefundAmt(), mchntOrderInfo.getBizStatus());
                    if (AmountUtil.compare(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getRefundAmt()) == 0) {
                        if ("01".equals(mchntOrderInfo.getBizSceneType())) {
                            if (BizStatusEnum.CONFIRM.getStatus().equals(mchntOrderInfo.getBizStatus())
                                    || BizStatusEnum.PART_REFUND.getStatus().equals(mchntOrderInfo.getBizStatus())) {
                                mchntOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
                            } else {
                                mchntOrderInfo.setBizStatus(BizStatusEnum.NOT_CONFIRM_REFUND.getStatus());
                            }
                        } else {
                            mchntOrderInfo.setBizStatus(BizStatusEnum.REFUND.getStatus());
                        }
                        xmlTreeUtil.setXmlTreeStringValue("MCHNTREFUNDTYPE" + mchntOrderInfo.getMchntNo(), AppParamConstant.YES);
                    } else {
                        if ("01".equals(mchntOrderInfo.getBizSceneType())) {
                            if (BizStatusEnum.CONFIRM.getStatus().equals(mchntOrderInfo.getBizStatus())
                                    || BizStatusEnum.PART_REFUND.getStatus().equals(mchntOrderInfo.getBizStatus())) {
                                mchntOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
                            } else {
                                mchntOrderInfo.setBizStatus(BizStatusEnum.NOT_CONFIRM_PART_REFUND.getStatus());
                            }
                        } else {
                            mchntOrderInfo.setBizStatus(BizStatusEnum.PART_REFUND.getStatus());
                        }
                        xmlTreeUtil.setXmlTreeStringValue("MCHNTREFUNDTYPE" + mchntOrderInfo.getMchntNo(), AppParamConstant.NO);
                    }
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                }
                Objects.requireNonNull(origPayOrderInfo).setBizStatus(origUserOrderInfo.getBizStatus());
                origPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

                //当调用通道退款成功后，更新原支付订单信息及累计商户限额
                if (BizStatusEnum.FINISH.getStatus().equals(needUpdateOrderInfo.getUserOrderInfo().getBizStatus())) {
                    //更新原支付订单状态
                    OrderService orderService = new OrderServiceImpl();
                    if (!orderService.updateOrderInfo(origUserOrderInfo, origMchntOrderInfoList, origMchneOrderDetailList, origPayOrderInfo)) {
                        rglog.error("更新原支付订单状态失败!");
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                    }
                    //更新商户限额
                    MchntService mchntService = new MchntServiceImpl();
                    List<MchntOrderInfo> mchntOrderInfoList = (List<MchntOrderInfo>) GlobalTransUtil.getCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST);
                    mchntService.updateMchntTransLimit(mchntOrderInfoList);
                }
            }
        } else if (TransStatusEnum.SYSTEM_REJECT.equals(transStatusEnum) && null != channelResponse) {
            if (ChannelEnum.UPAC.getChannelType().equals(channelCallCfg.getCallChannelId())) {
                Result<TokenConsumeRefundResponse> callResult = (Result<TokenConsumeRefundResponse>) channelResponse;
                TokenConsumeRefundResponse tokenConsumeRefundResponse = callResult.getResult();
                if ("04".equals(tokenConsumeRefundResponse.getRespCode())) {
                    return TransStatusEnum.TRANS_TIMEOUT;
                }
            }
        }
        return transStatusEnum;
    }
}
